package com.wen.qqrobot;

import com.wen.qqrobot.util.Shell;
import com.wen.qqrobot.util.StringUtil;
import com.wen.qqrobot.util.TimeUtil;
import com.wen.qqrobot.util.Xiaohuangji;
import iqq.im.QQActionListener;
import iqq.im.QQClient;
import iqq.im.QQException;
import iqq.im.WebQQClient;
import iqq.im.actor.ThreadActorDispatcher;
import iqq.im.bean.*;
import iqq.im.bean.content.ContentItem;
import iqq.im.bean.content.TextItem;
import iqq.im.core.QQConstants;
import iqq.im.event.*;

import javax.imageio.ImageIO;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * Created by wenwen on 2016/10/5.
 * version 1.0
 */
public class QQServer {

    private GroupFilter groupFilter = new GroupFilter();

    private Blacklist blacklist = new Blacklist();

    private Set<Long> admins = new HashSet<Long>();

    private Config config = Config.getInstance();

    private QQClient client;

    public QQServer() {
        client = new WebQQClient(config.getQQ(), config.getPassword(),
                new QQNotifyHandlerProxy(this), new ThreadActorDispatcher());
    }

    /**
     * 聊天消息通知
     *
     * @param event
     * @throws QQException
     */
    @QQNotifyHandler(QQNotifyEvent.Type.CHAT_MSG)
    public void processBuddyMsg(QQNotifyEvent event) throws QQException {
        QQMsg message = (QQMsg) event.getTarget();
        if (!isNeedReply(message) || isOldMessage(message)) {
            return;
        }
        //拼接消息
        StringBuilder text = new StringBuilder(100);
        List<ContentItem> items = message.getContentList();
        for (ContentItem item : items) {
            //只获取文本消息
            if (item.getType() == ContentItem.Type.TEXT) {
                String content = ((TextItem) item).getContent();
                text.append(StringUtil.repaceTabs(content)).append("\n");
            }
        }
        String textS = text.toString().trim();
        //消息过短则不处理
        if (textS.length() < 1) {
            textS = ">_<";
        }
        System.out.println("[" + TimeUtil.getDate() + "] "
                + message.getFrom().getNickname());
        System.out.println("消息内容: " + textS);

        String result = null;
        if (textS.startsWith("#")) {
            result = getShellResut(message.getFrom(), textS);
        } else {
            //获得小黄鸡结果
            result = Xiaohuangji.chat(textS);
        }

        //新建消息
        QQMsg myMessage = new QQMsg();
        //设置类型
        myMessage.setType(message.getType());
        if (message.getType() == QQMsg.Type.GROUP_MSG) {
            myMessage.setGroup(message.getGroup());
        }
        myMessage.setTo(message.getFrom());
        //设置内容
        myMessage.addContentItem(new TextItem(result));
        //发送消息
        this.client.sendMsg(myMessage, new QQActionListener() {
            @Override
            public void onActionEvent(QQActionEvent event) {
                //TODO 暂不处理
            }
        });
    }

    /**
     * 判断是否为旧消息（5秒前）
     *
     * @param message
     * @return
     */
    private boolean isOldMessage(QQMsg message) {
        Date date = message.getDate();
        Date nowData = new Date(System.currentTimeMillis() - 5000);
        return date.before(nowData);
    }

    /**
     * 判断是否有必要回复
     *
     * @param message
     * @return
     */
    private boolean isNeedReply(QQMsg message) {
        //获取消息类型
        QQMsg.Type type = message.getType();
        if (type == QQMsg.Type.GROUP_MSG) {
            if (!config.isSendGroup()) {
                return false;
            }
            String groupName = message.getGroup().getName();
            if (!this.groupFilter.contains(groupName)) {
                return false;
            }
        } else if (type == QQMsg.Type.BUDDY_MSG) {
            if (!config.isSendSingle()) {
                return false;
            }
        }
        String fromName = message.getFrom().getNickname();
        return !this.blacklist.contains(fromName);
    }

    private String getShellResut(QQUser user, String shell) {
        if (shell.startsWith("password:", 1)) {
            String pwd = shell.substring(10).trim();
            if (pwd.equals(config.getShellPassword())) {
                System.out.println(user.getNickname() + " Success!");
                this.admins.add(user.getUin());
                return user.getNickname() + " Success!";
            }
        } else {
            if (this.admins.contains(user.getUin())) {
                return Shell.exec(shell.substring(1));
            }
        }
        return "<(￣ ﹌ ￣)> 对不起，你没有限权~\n"
                + "发送 #password:设置的密码 来获取限权。";
    }

    /**
     * 被踢下线通知
     *
     * @param event
     */
    @QQNotifyHandler(QQNotifyEvent.Type.KICK_OFFLINE)
    protected void processKickOff(QQNotifyEvent event) {
        System.out.println("被踢下线: " + (String) event.getTarget());
    }

    /**
     * 需要验证码通知
     *
     * @param event
     * @throws IOException
     */
    @QQNotifyHandler(QQNotifyEvent.Type.CAPACHA_VERIFY)
    protected void processVerify(QQNotifyEvent event) throws IOException {
        QQNotifyEventArgs.ImageVerify verify = (QQNotifyEventArgs.ImageVerify) event.getTarget();
        ImageIO.write(verify.image, "png", new File("verify.png"));
        System.out.println(verify.reason);
        System.out.print("请输入在项目根目录下verify.png图片里面的验证码:");
        String code = new BufferedReader(new InputStreamReader(System.in)).readLine();
        client.submitVerify(code, event);
    }

    /**
     * 登录
     */
    public void login() {
        String ua = "Mozilla/5.0 (@os.name; @os.version; @os.arch)"
                + " AppleWebKit/537.36 (KHTML, like Gecko)"
                + " @appName Safari/537.36";
        ua = ua.replaceAll("@appName", QQConstants.USER_AGENT);
        ua = ua.replaceAll("@os.name", System.getProperty("os.name"));
        ua = ua.replaceAll("@os.version", System.getProperty("os.version"));
        ua = ua.replaceAll("@os.arch", System.getProperty("os.arch"));
        client.setHttpUserAgent(ua);
        this.loadUsersInfo();
        this.setTimer();
        this.startSmartRobot();
    }

    private void loadUsersInfo() {
        final QQActionListener listener = new QQActionListener() {
            @Override
            public void onActionEvent(QQActionEvent event) {
                System.out.println("LOGIN_STATUS:" + event.getType() + ":" + event.getTarget());
                if (event.getType() == QQActionEvent.Type.EVT_OK) {

                    //获取下用户信息
                    client.getUserInfo(client.getAccount(), new QQActionListener() {
                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            System.out.println("LOGIN_STATUS:" + event.getType() + ":" + event.getTarget());
                        }
                    });

                    // 获取好友列表..TODO.
                    // 不一定调用，可能会有本地缓存
                    client.getBuddyList(new QQActionListener() {

                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            // TODO Auto-generated method stub
                            System.out.println("******** " + event.getType()
                                    + " ********");
                            if (event.getType() == QQActionEvent.Type.EVT_OK) {
//                                System.out.println("******** 好友列表  ********");
//                                List<QQCategory> qqCategoryList = (List<QQCategory>) event
//                                        .getTarget();
//
//                                for (QQCategory c : qqCategoryList) {
//                                    System.out.println("分组名称:" + c.getName());
//                                    List<QQBuddy> buddyList = c.getBuddyList();
//                                    for (QQBuddy b : buddyList) {
//                                        System.out.println("---- QQ nick:"
//                                                + b.getNickname()
//                                                + " markname:"
//                                                + b.getMarkname() + " uin:"
//                                                + b.getUin() + " isVip:"
//                                                + b.isVip() + " vip_level:"
//                                                + b.getVipLevel());
//                                    }
//
//                                }
                            } else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
                                System.out.println("** 好友列表获取失败，处理重新获取");
                            }
                        }
                    });
                    // 获取群列表
                    client.getGroupList(new QQActionListener() {

                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            if (event.getType() == QQActionEvent.Type.EVT_OK) {
                                for (QQGroup g : client.getGroupList()) {
                                    client.getGroupInfo(g, null);
//                                    System.out.println("Group: " + g.getName());
                                }
                            }
                        }
                    });
                    // 获取讨论组列表
                    client.getDiscuzList(new QQActionListener() {

                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            if (event.getType() == QQActionEvent.Type.EVT_OK) {
                                for (QQDiscuz d : client.getDiscuzList()) {
                                    client.getDiscuzInfo(d, null);
//                                    System.out.println("Discuz: " + d.getName());
                                }
                            }
                        }
                    });
                    client.getOnlineList(new QQActionListener() {

                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            // TODO Auto-generated method stub
                            System.out.println("******** " + event.getType()
                                    + " ********");
                            if (event.getType() == QQActionEvent.Type.EVT_OK) {
//                                System.out.println("******** 在线好友列表  ********");
//                                List<QQCategory> qqCategoryList = (List<QQCategory>) event
//                                        .getTarget();
//
//                                for (QQCategory c : qqCategoryList) {
//                                    System.out.println("分组名称:" + c.getName());
//                                    List<QQBuddy> buddyList = c.getBuddyList();
//                                    for (QQBuddy b : buddyList) {
//                                        System.out.println("---- QQ nick:"
//                                                + b.getNickname()
//                                                + " markname:"
//                                                + b.getMarkname() + " uin:"
//                                                + b.getUin() + " isVip:"
//                                                + b.isVip() + " vip_level:"
//                                                + b.getVipLevel());
//                                    }
//
//                                }
                            } else if (event.getType() == QQActionEvent.Type.EVT_ERROR) {
                                System.out.println("** 在线好友列表获取失败，处理重新获取");
                            }
                        }
                    });
                    // 查群测试
                    QQGroupSearchList list = new QQGroupSearchList();
                    list.setKeyStr("QQ");
                    client.searchGroupGetList(list, new QQActionListener() {
                        @Override
                        public void onActionEvent(QQActionEvent event) {
                            if (event.getType() == QQActionEvent.Type.EVT_OK) {

                            }
                        }
                    });
                    //启动轮询时，需要获取所有好友、群成员、讨论组成员
                    //所有的逻辑完了后，启动消息轮询
                    client.beginPollMsg();
                }
            }
        };
        client.login(QQStatus.ONLINE, listener);
    }

    private void startSmartRobot() {
        client.getOnlineList(null);
    }

    private void setTimer() {
        Timer timer = new Timer(true);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                admins.clear();
                System.out.println("Clear admins.");
            }
        }, 300000, 300000);
    }

    public GroupFilter getGroupFilter() {
        return groupFilter;
    }

    public void setGroupFilter(GroupFilter groupFilter) {
        this.groupFilter = groupFilter;
    }

    public Blacklist getBlacklist() {
        return blacklist;
    }

    public void setBlacklist(Blacklist blacklist) {
        this.blacklist = blacklist;
    }

}
